package qlsl.androiddesign.api.http.xutils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

import org.apache.http.cookie.Cookie;
import org.apache.http.impl.client.DefaultHttpClient;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;
import java.util.TreeMap;

import qlsl.androiddesign.api.application.SoftwareApplication;
import qlsl.androiddesign.api.util.commonutil.Log;
import qlsl.androiddesign.api.util.commonutil.SPUtils;
import qlsl.androiddesign.api.util.commonutil.StringUtils;
import qlsl.androiddesign.api.util.commonutil.ValueUtil;
import xutils.HttpUtils;
import xutils.exception.HttpException;
import xutils.http.RequestParams;
import xutils.http.ResponseStream;
import xutils.http.callback.RequestCallBack;
import xutils.http.client.HttpRequest;


/**
 * 类描述：基于xutils的网络请求封装类,暂未作并发考虑
 * 需要传入的键：****
 * 传入的值类型：****
 * 传入的值含义：****
 * 是否必传：****
 * 作者：郑朝军 on 2017/6/14 11:29
 * 邮箱：1250393285@qq.com
 * 公司：武汉智博创享科技有限公司
 * 修改人：郑朝军 on 2017/6/14 11:29
 * 修改备注：
 */
public class HttpProtocol extends Protocol
{
    private TreeMap<String, Object> params = new TreeMap<String, Object>();

    private HttpRequest.HttpMethod httpMethod;

    private boolean removeUserParam;

    public static final String COOKIE_KEY = "website_sessionid";

    public HttpProtocol()
    {
//        url = "http://kw.runfkj.com/";
        url = "http://kw.runfkj.com/";
    }

    public HttpProtocol setMethod(String method)
    {
        super.setMethod(method);
//        url += ("appservice/" + method + ".action");
        url = method;
        return this;
    }

    public HttpProtocol addParam(String key, Object value)
    {
        if (value instanceof Boolean)
        {
            value = (Boolean) value ? 1 : 0;
        }
        if (value != null)
        {
            if (key.equals("userid") && removeUserParam)
            {
                return this;
            }
            params.put(key, value);
        }
        return this;
    }

    public HttpProtocol removeUserParam()
    {
        removeUserParam = true;
        return this;
    }

    private void addSignedParams()
    {

    }

    private RequestParams convertParams()
    {
        RequestParams requestParams = new RequestParams("UTF-8");
        Iterator<Entry<String, Object>> iterator = params.entrySet().iterator();
        while (iterator.hasNext())
        {
            Entry<String, Object> entry = iterator.next();
            String key = entry.getKey();
            Object value = entry.getValue();

            if (httpMethod == HttpRequest.HttpMethod.GET)
            {
                requestParams.addQueryStringParameter(key, value + "");
            }
            else if (httpMethod == HttpRequest.HttpMethod.POST)
            {
                requestParams.addBodyParameter(key, value + "");
            }
        }
        return requestParams;
    }

    /////////////////////////////////提供网络请求的方法/////////////////////////////////////////////////////////////////////

    /**
     * 同步请求,必须异步调用<br/>
     * GET请求<br/>
     */
    public JSONObject get()
    {
        httpMethod = HttpRequest.HttpMethod.GET;
        return requestGet();
    }

    /**
     * 同步请求,必须异步调用<br/>
     * POST请求<br/>
     */
    public JSONObject post()
    {
        httpMethod = HttpRequest.HttpMethod.POST;
        return requestPost();
    }

    /**
     * 异步请求<br/>
     * 上传文件<br/>
     */
    public <T> void uploadFile(File file, FileType type,
                               RequestCallBack<T> callBack)
    {
        httpMethod = HttpRequest.HttpMethod.POST;
        requestUploadFile(file, type, callBack);
    }

    /**
     * 异步请求<br/>
     * 批量上传文件<br/>
     */
    public <T> void uploadFiles(List<File> files, FileType type,
                                RequestCallBack<T> callBack)
    {
        if (files.size() == 0)
        {
            return;
        }
        httpMethod = HttpRequest.HttpMethod.POST;
        requestUploadFiles(files, type, callBack);
    }

    /**
     * 异步请求<br/>
     * 批量上传文件<br/>
     * 不检是否包含文件<br/>
     */
    public <T> void uploadFilesUnchecked(List<File> files, FileType type,
                                         RequestCallBack<T> callBack)
    {
        httpMethod = HttpRequest.HttpMethod.POST;
        requestUploadFiles(files, type, callBack);
    }

    /**
     * type:[0,1]代表[get,post]<br/>
     */
    public JSONObject request(int type, RequestParams requestParams)
    {
        HttpUtils http = createDefaultHttpUtils();
        try
        {
            requestParams.addHeader("Connection", "Keep-Alive");
            ResponseStream responseStream = null;
            if (type == 0)
            {
                responseStream = http.sendSync(HttpRequest.HttpMethod.GET, url,
                        requestParams);
            }
            else if (type == 1)
            {
                responseStream = http.sendSync(HttpRequest.HttpMethod.POST,
                        url, requestParams);
            }
            String responseStr = responseStream.readString();
            JSONObject jsonObject = JSON.parseObject(ValueUtil.isEmpty(responseStr) ? responseStr
                    : StringUtils.jaToJo(responseStr));
            return jsonObject;
        }
        catch (HttpException e)
        {
            e.printStackTrace();
            outputException(e);
        }
        catch (IOException e)
        {
            e.printStackTrace();
            outputException(e);
        }
        return null;
    }

    public JSONObject requestGet()
    {
        HttpUtils http = createDefaultHttpUtils();
        try
        {
            ResponseStream responseStream = http.sendSync(
                    HttpRequest.HttpMethod.GET, url, prepareRequestParams());
            String responseStr = responseStream.readString();

            JSONObject jsonObject = JSON.parseObject(ValueUtil.isEmpty(responseStr) ? responseStr
                    : StringUtils.jaToJo(responseStr));
            return jsonObject;
        }
        catch (HttpException e)
        {
            e.printStackTrace();
            outputException(e);
        }
        catch (IOException e)
        {
            e.printStackTrace();
            outputException(e);
        }
        return null;
    }

    public JSONObject requestPost()
    {
        HttpUtils http = createDefaultHttpUtils();
        try
        {
            ResponseStream responseStream = http.sendSync(
                    HttpRequest.HttpMethod.POST, url, prepareRequestParams());

            getCookieFromHttpUtils(http);
            String responseStr = responseStream.readString();

            JSONObject jsonObject = JSON.parseObject(ValueUtil.isEmpty(responseStr) ? responseStr
                    : StringUtils.jaToJo(responseStr));
            return jsonObject;
        }
        catch (HttpException e)
        {
            e.printStackTrace();
            outputException(e);
        }
        catch (IOException e)
        {
            e.printStackTrace();
            outputException(e);
        }
        return null;
    }

    public <T> void requestUploadFile(File file, FileType type,
                                      RequestCallBack<T> callBack)
    {
        HttpUtils http = createDefaultHttpUtils();
        RequestParams requestParams = prepareRequestParams();
        try
        {
            String key_suffix = KEY_PICTURE;
            if (type == FileType.PICTURE)
            {
                key_suffix = KEY_PICTURE;
            }
            else if (type == FileType.AUDIO)
            {
                key_suffix = KEY_AUDIO;
            }

            requestParams.setContentType("multipart/form-data; boundary=" + "----------" + System
                    .currentTimeMillis());

            requestParams.addBodyParameter(key_suffix,
                    new FileInputStream(file), file.length(), file.getName(),
                    "application/octet-stream");
            http.send(HttpRequest.HttpMethod.POST, url, requestParams, callBack);
        }
        catch (Exception e)
        {
            e.printStackTrace();
            outputException(e);
        }
    }

    public <T> void requestUploadFiles(List<File> files, FileType type,
                                       RequestCallBack<T> callBack)
    {
        HttpUtils http = createDefaultHttpUtils();
        RequestParams requestParams = prepareRequestParams();
        try
        {
            String key_suffix = KEY_PICTURE;
            if (type == FileType.PICTURE)
            {
                key_suffix = KEY_PICTURE;
            }
            else if (type == FileType.AUDIO)
            {
                key_suffix = KEY_AUDIO;
            }
            if (files != null && files.size() != 0)
            {
                for (int index = 0; index < files.size(); index++)
                {
                    requestParams.addBodyParameter(key_suffix + (index + 1)
                            , new FileInputStream(files.get(index))
                            , files.get(index).length(), files.get(index).getName()
                            , "application/octet-stream");
                }
            }
            else
            {
                // requestParams.addHeader("Content-Type",
                // "application/x-www-form-urlencoded");
                // requestParams.addHeader("Content-Type",
                // "application/octet-stream");
                // requestParams.addHeader("Content-Type",
                // "multipart/form-data;boundary="+new Date().getTime());
                // requestParams.addBodyParameter("key_file_empty",new
                // File("path_empty"));
            }
            requestParams.setContentType("multipart/form-data; boundary=" + "----------" + System
                    .currentTimeMillis());
            http.send(HttpRequest.HttpMethod.POST, url, requestParams, callBack);
        }
        catch (Exception e)
        {
            e.printStackTrace();
            outputException(e);
        }
    }

    private RequestParams prepareRequestParams()
    {
//         addSignedParams();
        RequestParams requestParams = convertParams();
//         String paramsStr = HttpMethod.getParamsStr(params);
//         String signStr = HttpMethod.getSignStr(paramsStr);
        if (httpMethod == HttpRequest.HttpMethod.GET)
        {
            // requestParams.addQueryStringParameter(HttpKeyConstant.PARAM_SIGN,
            // signStr);
            // requestParams.addQueryStringParameter(HttpKeyConstant.PARAM_PARTNER,
            // HttpKeyConstant.VALUE_PARTNER);
        }
        else if (httpMethod == HttpRequest.HttpMethod.POST)
        {
            // requestParams.addBodyParameter(HttpKeyConstant.PARAM_SIGN,
            // signStr);
            // requestParams.addBodyParameter(HttpKeyConstant.PARAM_PARTNER,
            // HttpKeyConstant.VALUE_PARTNER);
        }
        // addParam(HttpKeyConstant.PARAM_SIGN, signStr);
        // addParam(HttpKeyConstant.PARAM_PARTNER,
        // HttpKeyConstant.VALUE_PARTNER);
        requestParams.addHeader("Connection", "Keep-Alive");
//        requestParams.addHeader("User-Agent", AppMethod.getUserAgent());
        requestParams.addHeader("Content-Type", "application/x-www-form-urlencoded");
        requestParams.setHeader("Cookie", "JSESSIONID=" + SPUtils.get(SoftwareApplication.getInstance(), COOKIE_KEY, null));
        return requestParams;
    }

    private HttpUtils createDefaultHttpUtils()
    {
        HttpUtils http = new HttpUtils();
        http.configDefaultHttpCacheExpiry(1000 * 10);
        http.configRequestRetryCount(1);
        return http;
    }
    /////////////////////////////////结束/////////////////////////////////////////////////////////////////////

    /**
     * 输出网络错误详情<br/>
     */
    private void outputException(Exception e)
    {
        Log.e(getClass().getName() + "<br/>" + e);
    }

    /**
     * 获取基本url与参数的拼接字符串<br/>
     * 只能在网络请求返回之后调用，才能获取准确的参数<br/>
     */
    public String getUrl()
    {
        if (params.size() == 0)
        {
            return url;
        }
        else
        {
            StringBuffer sb = new StringBuffer(url + "?");
            Iterator<Entry<String, Object>> iterator = params.entrySet()
                    .iterator();
            while (iterator.hasNext())
            {
                Entry<String, Object> entry = iterator.next();
                String key = entry.getKey();
                Object value = entry.getValue();
                sb.append(key + "=" + value + "&");
            }
            sb.deleteCharAt(sb.length() - 1);
            return sb.toString();
        }
    }

    /**
     * 获取参数<br/>
     * 只能在网络请求返回之后调用，才能获取准确的参数<br/>
     */
    public Object getParams()
    {
        return params;
    }

    /**
     * 清除静态数据<br/>
     */
    public static void clearStaticData()
    {
        // tick = 0;
        // lastTime = 0;
    }

    /**
     * 从HttpUtils中获取cookie，并且PUT cookie值
     *
     * @param http
     */
    public void getCookieFromHttpUtils(HttpUtils http)
    {
        List<Cookie> cookies = ((DefaultHttpClient) http.getHttpClient()).getCookieStore().getCookies();
        for (Cookie cookie : cookies)
        {
            if ("JSESSIONID".equals(cookie.getName()))
            {
                SPUtils.put(SoftwareApplication.getInstance(), COOKIE_KEY, cookie.getValue());
            }
        }
    }
}
